#include "Matrix.h"
#include <vector>

namespace HW2
{

	Matrix::Matrix()
	{
		data = std::vector<double>(16,0);
	}

	double& Matrix::get(int r, int c)
	{
		return data[(r-1)*4+c-1];
	}
	double& Matrix::operator()(int r, int c)
	{
		return get(r,c);
	}
	Matrix Matrix::operator*(Matrix &other)
	{
		Matrix result;
		for(int i = 1; i <= 4; ++i)
			for(int j = 1; j <= 4; ++j)
				for(int k = 1; k <= 4; ++k)
					result(i,j) += get(i,k) * other(k,j);
		return result;
	}

	void Matrix::operator*=(Matrix &other)
	{
		Matrix result = (*this) * other;
		*this = result;
	}
	void Matrix::multiplyLeftSide(Matrix &other)
	{
		other*= *this;
		*this = other;
	}
	void Matrix::multiplySide(Matrix &other, bool leftSide /* = false */)
	{
		if(leftSide)
			multiplyLeftSide(other);
		else
			(*this)*= other;
	}

	Matrix Matrix::I()
	{
		Matrix result;
		result(1,1) = result(2,2) = result(3,3) = result(4,4) = 1;
		return result;

	}

	Matrix Matrix::perspective(double d)
	{
		Matrix result;
		result(1,1) = result(2,2) = result(3,3) = 1;
		result(3,4) = 1/d;
		return result;
	}

	Matrix Matrix::perspectiveWarp(double far, double near)
	{
		Matrix result;
		result(1,1) = result(2,2) = 1;
		result(3,3) = far/(far-near);
		result(3,4) = 1/far;
		result(4,3) = (-far*near)/(far-near);
		return result;
	}
	Matrix Matrix::orthographic()
	{
		Matrix result;
		result(1,1) = result(2,2) = result(4,4) = 1;
		return result;

	}


	Matrix Matrix::scale(double ratio)
	{
		return scale(ratio, ratio, ratio);
	}

	Matrix Matrix::scale(double x, double y, double z)
	{
		Matrix result;
		result(1,1) = x;
		result(2,2) = y;
		result(3,3) = z;
		result(4,4) = 1;
		return result;
	}





	Matrix Matrix::move(double x, double y, double z)
	{
		Matrix result;
		result(1,1) = result(2,2) = result(3,3) = result(4,4) = 1;
		result(4,1) = x;
		result(4,2) = y;
		result(4,3) = z;
		return result;
	}

	Matrix Matrix::rotateX(double a){
		Matrix m;
		m(2,2) = cos(a);
		m(2,3) = sin(a);
		m(3,2) = -sin(a);
		m(3,3) = cos(a);
		m(1,1) = m(4,4) = 1;
		return m;
	}
	Matrix Matrix::rotateY(double a){
		Matrix m;
		m(1,1) = cos(a);
		m(1,3) = sin(a);
		m(3,1) = -sin(a);
		m(3,3) = cos(a);
		m(2,2) = m(4,4) = 1;
		return m;
	}
	Matrix Matrix::rotateZ(double a){
		Matrix m;
		m(1,1) = cos(a);
		m(1,2) = sin(a);
		m(2,1) = -sin(a);
		m(2,2) = cos(a);
		m(3,3) = m(4,4) = 1;
		return m;
	}


}